/*
 *  $Id$
 *  Copyright [2010] [Panxiaobo] 
 *  Licensed under the Apache License, Version 2.0 (the "License"); 
 *  you may not use this file except in compliance with the License. 
 *  You may obtain a copy of the License at
 *  
 *     http://www.apache.org/licenses/LICENSE-2.0
 *     
 *  Unless required by applicable law or agreed to in writing, software 
 *  distributed under the License is distributed on an "AS IS" BASIS, 
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 *  See the License for the specific language governing permissions and 
 *  limitations under the License. 
 */
package pxb.openid.util;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import pxb.openid.OpenIdException;

/**
 * HmacSha算法的工具类
 * 
 * @author Panxiaobo
 * 
 */
public class Mac {

    /**
     * 生成hmacshax加密算法的密钥
     * 
     * @param x
     *            1或者256
     * @return
     * @throws IllegalArgumentException
     */
    public static byte[] generateKeyHmacShax(int x) throws IllegalArgumentException {
        if (x != 1 && x != 256) {
            throw new IllegalArgumentException("hmacshax的x值必须为1或者256");
        }
        KeyGenerator keyGen;
        try {
            keyGen = KeyGenerator.getInstance("hmacsha" + x);
        } catch (NoSuchAlgorithmException e) {
            throw new OpenIdException("没有算法: hmacsha" + x, e);
        }
        keyGen.init(x == 1 ? 160 : 256);
        SecretKey macKey = keyGen.generateKey();
        return macKey.getEncoded();
    }

    /**
     * 使用HmacSha1签名
     * 
     * @param key
     *            密钥
     * @param text
     *            待签名文本
     * @return
     */
    public static byte[] hmacSha1(byte[] key, byte[] text) {
        return hmacShaX("HMACSHA1", key, text);
    }

    /**
     * 使用HmacSha1签名
     * 
     * @param key
     *            密钥
     * @param text
     *            待签名文本
     * @return
     */
    public static byte[] hmacSha256(byte[] key, byte[] text) {
        return hmacShaX("HMACSHA256", key, text);
    }

    /**
     * 使用HmacShax签名
     * 
     * @param algorithm
     *            签名算法
     * @param key
     *            密钥
     * @param text
     *            待签名文本
     * @return
     */
    private static byte[] hmacShaX(String algorithm, byte[] key, byte[] text) {
        SecretKey sk = new SecretKeySpec(key, algorithm);
        javax.crypto.Mac m;
        try {
            m = javax.crypto.Mac.getInstance(sk.getAlgorithm());
            m.init(sk);
            return m.doFinal(text);
        } catch (NoSuchAlgorithmException e) {
            throw new OpenIdException("没有算法: " + algorithm, e);
        } catch (InvalidKeyException e) {
            throw new OpenIdException("不合法的密钥", e);
        } catch (Exception e) {
            throw new OpenIdException("签名时发生异常", e);
        }
    }
}
